#pragma once

#define SWEGL_DXWRAPPER_NYI() { static bool first = true; if (first) { first = false; sweglInfo("%s: NYI\n", SWEGL_FUNCTION); } }

#define SWEGL_DXWRAPPER_DECLARE_IUNKNOWN(_class_, _parentClass_) \
	private: \
	ULONG m_refCount; \
	public: \
    HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj); \
    ULONG __stdcall AddRef(); \
    ULONG __stdcall Release()

#define SWEGL_DXWRAPPER_IMPLEMENT_IUNKNOWN(_class_, _parentClass_) \
	HRESULT _class_::QueryInterface(REFIID riid, void** ppvObj) \
	{ \
		sweglInfo("%s: %#lx %#x %#x\n", SWEGL_FUNCTION, riid.Data1, riid.Data2, riid.Data3); \
		if (IsEqualIID(riid, IID_IUnknown)) \
			*ppvObj = (void *) this; \
		else if (IsEqualIID(riid, IID_IDirect3DDevice9)) \
			*ppvObj = (void *) this; \
		/*else if (IsEqualIID(riid, IID_IDirect3DDevice9Ex))*/ \
			/* *ppvObj = (void *) this;*/ \
		else \
		{ \
			return E_NOINTERFACE; \
		} \
		m_refCount++; \
		return S_OK; \
	} \
	ULONG _class_::AddRef() \
	{ \
		sweglInfo("%s: m_refCount = %u\n", SWEGL_FUNCTION, m_refCount); \
		return ++m_refCount; \
	} \
	ULONG _class_::Release() \
	{ \
		sweglInfo("%s: m_refCount = %u\n", SWEGL_FUNCTION, m_refCount); \
		if (--m_refCount == 0) \
		{ \
  			delete this; \
			return 0; \
		} \
		return m_refCount; \
	}

#define SWEGL_DXWRAPPER_INIT_IUNKNOWN() m_refCount = 1

#define SWEGL_DXWRAPPER_DECLARE_RESOURCE(_class_, _parentClass_) \
	HRESULT __stdcall GetDevice(IDirect3DDevice9** ppDevice); \
	HRESULT __stdcall SetPrivateData(REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags); \
	HRESULT __stdcall GetPrivateData(REFGUID refguid,void* pData,DWORD* pSizeOfData); \
	HRESULT __stdcall FreePrivateData(REFGUID refguid); \
	DWORD __stdcall SetPriority(DWORD PriorityNew); \
	DWORD __stdcall GetPriority(); \
	void __stdcall PreLoad(); \
	D3DRESOURCETYPE __stdcall GetType()

class myIDirect3D9 : public IDirect3D9
{
public:
    myIDirect3D9();
    virtual ~myIDirect3D9();

	SWEGL_DXWRAPPER_DECLARE_IUNKNOWN(myIDirect3D9, IDirect3D9);

    // The original DX9 function definitions
    HRESULT  __stdcall RegisterSoftwareDevice(void* pInitializeFunction);
	UINT     __stdcall GetAdapterCount();
	HRESULT  __stdcall GetAdapterIdentifier(UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) ;
    UINT     __stdcall GetAdapterModeCount(UINT Adapter, D3DFORMAT Format);
    HRESULT  __stdcall EnumAdapterModes(UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) ;
    HRESULT  __stdcall GetAdapterDisplayMode( UINT Adapter,D3DDISPLAYMODE* pMode) ;
    HRESULT  __stdcall CheckDeviceType(UINT iAdapter,D3DDEVTYPE DevType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) ;
    HRESULT  __stdcall CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) ;
    HRESULT  __stdcall CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) ;
    HRESULT  __stdcall CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) ;
    HRESULT  __stdcall CheckDeviceFormatConversion(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat);
    HRESULT  __stdcall GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) ;
	HMONITOR __stdcall GetAdapterMonitor(UINT Adapter) ;
	HRESULT  __stdcall CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) ;
    // The original DX9 function definitions

	/*** IDirect3D9Ex methods ***/
    virtual UINT __stdcall GetAdapterModeCountEx(UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter);
    virtual HRESULT __stdcall EnumAdapterModesEx(UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode);
    virtual HRESULT __stdcall GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation);
    virtual HRESULT __stdcall CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, struct IDirect3DDevice9Ex **ppReturnedDeviceInterface);
    virtual HRESULT __stdcall GetAdapterLUID(UINT Adatper, LUID *pLUID);
private:
};
